package com.lineage.server.datatables.sql;

import com.lineage.DatabaseFactory;
import com.lineage.server.datatables.CharObjidTable;
import com.lineage.server.datatables.QuestTable;
import com.lineage.server.datatables.storage.CharacterQuestStorage;
import com.lineage.server.templates.CharQuest;
import com.lineage.server.templates.L1Quest;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CharacterQuestTable implements CharacterQuestStorage {
  public static final Log _log = LogFactory.getLog(CharacterQuestTable.class);
  
  private static final Map<Integer, HashMap<Integer, CharQuest>> _questList = new HashMap<>();
  
  public void load() {
    delete();
    PerformanceTimer timer = new PerformanceTimer();
    Connection co = null;
    PreparedStatement pm = null;
    ResultSet rs = null;
    try {
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement("SELECT * FROM `character_quests`");
      rs = pm.executeQuery();
      while (rs.next()) {
        int char_id = rs.getInt("char_id");
        if (CharObjidTable.get().isChar(char_id) != null) {
          int key = rs.getInt("quest_id");
          switch (key) {
            case 110:
            case 117:
            case 137:
            case 139:
            case 147:
              continue;
          } 
          int quest_step = rs.getInt("quest_step");
          int[] mob_count = getArray(rs.getString("mob_count"));
          CharQuest quest = new CharQuest();
          quest.set_quest_step(quest_step);
          quest.set_mob_count(mob_count);
          HashMap<Integer, CharQuest> hsMap = _questList.get(new Integer(char_id));
          if (hsMap == null) {
            hsMap = new HashMap<>();
            hsMap.put(new Integer(key), quest);
            _questList.put(new Integer(char_id), hsMap);
            continue;
          } 
          hsMap.put(new Integer(key), quest);
          continue;
        } 
        delete(char_id);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
    _log
      .info("载入人物任务纪录资料数量: " + _questList.size() + "(" + timer.get() + "ms)");
  }
  
  private static void delete() {
    deleteData(110);
    deleteData(117);
    deleteData(137);
    deleteData(139);
    deleteData(147);
  }
  
  public static void deleteData(int questid) {
    Connection co = null;
    PreparedStatement pm = null;
    try {
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement("DELETE FROM `character_quests` WHERE `quest_id`=?");
      pm.setInt(1, questid);
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  private static void delete(int objid) {
    _questList.remove(Integer.valueOf(objid));
    Connection co = null;
    PreparedStatement pm = null;
    try {
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement("DELETE FROM `character_quests` WHERE `char_id`=?");
      pm.setInt(1, objid);
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  public Map<Integer, CharQuest> get(int char_id) {
    return _questList.get(new Integer(char_id));
  }
  
  public void storeQuest(int char_id, int key, CharQuest value) {
    HashMap<Integer, CharQuest> hsMap = _questList.get(new Integer(char_id));
    if (hsMap == null) {
      hsMap = new HashMap<>();
      hsMap.put(new Integer(key), value);
      _questList.put(new Integer(char_id), hsMap);
    } else {
      hsMap.put(new Integer(key), value);
    } 
    L1Quest quest = null;
    if (value.get_quest_step() == 1)
      quest = QuestTable.get().getTemplate(key); 
    Connection co = null;
    PreparedStatement pm = null;
    try {
      String add = "";
      if (quest != null)
        add = ",`note`=?"; 
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement(
          "INSERT INTO `character_quests` SET `char_id`=?,`quest_id`=?,`quest_step`=?,`mob_count`=?" + add);
      int i = 0;
      pm.setInt(++i, char_id);
      pm.setInt(++i, key);
      pm.setInt(++i, value.get_quest_step());
      pm.setString(++i, getStatus(value.get_mob_count()));
      if (quest != null)
        pm.setString(++i, quest.get_note()); 
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  public void storeQuest2(int char_id, int key, int value) {
    Connection co = null;
    PreparedStatement pm = null;
    try {
      String add = "";
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement(
          "INSERT INTO `character_quests` SET `char_id`=?,`quest_id`=?,`quest_step`=?");
      int i = 0;
      pm.setInt(++i, char_id);
      pm.setInt(++i, key);
      pm.setInt(++i, value);
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  public void updateQuest(int char_id, int key, CharQuest value) {
    HashMap<Integer, CharQuest> hsMap = _questList.get(new Integer(char_id));
    if (hsMap == null) {
      hsMap = new HashMap<>();
      hsMap.put(new Integer(key), value);
      _questList.put(new Integer(char_id), hsMap);
    } else {
      hsMap.put(new Integer(key), value);
    } 
    Connection co = null;
    PreparedStatement pm = null;
    try {
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement(
          "UPDATE `character_quests` SET `quest_step`=?, `mob_count`=? WHERE `char_id`=? AND `quest_id`=?");
      int i = 0;
      pm.setInt(++i, value.get_quest_step());
      pm.setString(++i, getStatus(value.get_mob_count()));
      pm.setInt(++i, char_id);
      pm.setInt(++i, key);
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  public void delQuest(int char_id, int key) {
    HashMap<Integer, CharQuest> hsMap = _questList.get(new Integer(char_id));
    if (hsMap == null)
      return; 
    hsMap.remove(Integer.valueOf(key));
    Connection co = null;
    PreparedStatement pm = null;
    try {
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement("DELETE FROM `character_quests` WHERE `char_id`=? AND `quest_id`=?");
      int i = 0;
      pm.setInt(++i, char_id);
      pm.setInt(++i, key);
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  public void delQuest2(int questId) {
    Map<Integer, HashMap<Integer, CharQuest>> hsMap = _questList;
    Set<Integer> keySet = hsMap.keySet();
    Iterator<Integer> iterator = keySet.iterator();
    while (iterator.hasNext()) {
      Integer charId = iterator.next();
      HashMap<Integer, CharQuest> pchasQuest = _questList
        .get(new Integer(charId.intValue()));
      if (pchasQuest == null)
        continue; 
      pchasQuest.remove(Integer.valueOf(questId));
    } 
    Connection co = null;
    PreparedStatement pm = null;
    try {
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement("DELETE FROM `character_quests` WHERE `quest_id`=?");
      int i = 0;
      pm.setInt(++i, questId);
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
  
  private static int[] getArray(String s) {
    if (s == null || s.equals(""))
      return null; 
    StringTokenizer st = new StringTokenizer(s, ",");
    int iSize = st.countTokens();
    String sTemp = null;
    int[] iReturn = new int[iSize];
    int i = 0;
    while (i < iSize) {
      sTemp = st.nextToken();
      iReturn[i] = Integer.parseInt(sTemp);
      i++;
    } 
    return iReturn;
  }
  
  private static String getStatus(int[] status) {
    if (status == null)
      return "0"; 
    StringBuilder result = new StringBuilder();
    try {
      int statussize = status.length;
      int i = 0;
      while (i < statussize) {
        if (i > 0)
          result.append(","); 
        result.append(status[i]);
        i++;
      } 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
    return result.toString();
  }
  
  private void cleanMissionStatus() {
    Connection con = null;
    PreparedStatement pstm = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("DELETE FROM character_quests WHERE clean = 1");
      pstm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
      return;
    } finally {
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
  }
  
  public void storeQuest(int char_id, int key, CharQuest value, int clean) {
    HashMap<Integer, CharQuest> hsMap = _questList.get(new Integer(char_id));
    if (hsMap == null) {
      hsMap = new HashMap<>();
      hsMap.put(new Integer(key), value);
      _questList.put(new Integer(char_id), hsMap);
    } else {
      hsMap.put(new Integer(key), value);
    } 
    L1Quest quest = null;
    if (value.get_quest_step() == 1)
      quest = QuestTable.get().getTemplate(key); 
    Connection co = null;
    PreparedStatement pm = null;
    try {
      String add = "";
      if (quest != null)
        add = ",`note`=?"; 
      co = DatabaseFactory.get().getConnection();
      pm = co.prepareStatement(
          "INSERT INTO `character_quests` SET `char_id`=?,`quest_id`=?,`quest_step`=?,`clean`=?,`mob_count`=?" + 
          add);
      int i = 0;
      pm.setInt(++i, char_id);
      pm.setInt(++i, key);
      pm.setInt(++i, value.get_quest_step());
      pm.setInt(++i, clean);
      pm.setString(++i, getStatus(value.get_mob_count()));
      if (quest != null)
        pm.setString(++i, quest.get_note()); 
      pm.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pm);
      SQLUtil.close(co);
    } 
  }
}
